JetGlobalsDefaults['Implementation', 'JetCounts'] := 'monomial': 
JetGlobalsDefaults['Implementation', 'Jets'] := 'MM':

GetParameter := proc()
  global JetGlobalsDefaults, JetGlobals;
  if assigned(JetGlobals[args]) then JetGlobals[args]
  elif assigned(JetGlobalsDefaults[args]) then JetGlobalsDefaults[args]
  else error "unknown parameter(s) '%0'.", args
  fi
end:

jetCountsImplementationModule := getCountsImplementationModule(GetParameter('Implementation', 'JetCounts'), 
                                                         'DefineGlobalTypes'=false): 
if GetParameter('Implementation', 'Jets')='MM' then 
  jetsImplementationModule := module()
      option package;
      uses jetCountsImplementationModule;

      export jfvar, jcount, varorder, jetorder, jetorders,
       jet, Jet, JET,
       refresh,
       `count//seq`,
       `type/b/jcount`, `type/b/jcount1`, # underlying count types
       `type/j/var`;
      
      global `b/var/list`, `b/var/s`, `jet/aliases`,
        `pd//tab`,
        `vars/TD`,`vars/TD/1`,
        `pd/TD`,`pd/TD/1`,
        `pars/TD`,`pars/TD/1`,
        `unks/TD`,`unks/TD/1`,
        `Vars/TD`,`Vars/TD/1`;
        
        
      local `jcount/inner`, `bcount//str`, `bcount//str/_`,
        `simpl/JET`, remembertable,
        `refresh/1`, `refresh/list`;
  
        
      
      TypeTools:-AddType(`b/jcount`,      `test/b/count`); 
      TypeTools:-AddType(`b/jcount1`,     `test/b/count1`); 
      
      # Jet variables are unassigned calls to 'JET'.
      
     TypeTools:-AddType(`j/var`, specfunc(anything,JET)):
      
      # fvar(jet(u,x)) = u,  fvar(u) = u
      jfvar := proc(j)  
        option inline;
        `if`( type(j, name), # fast but no fibre variable check
              j, op(1,j))
      end:
      
      
      # jcount(jet(u,x)) = x,  jcount(u) = 1
      jcount := proc(j) `count/convert/normal`(`jcount/inner`(j)) end:
      
      `jcount/inner` := proc(j)  
        option inline;
        `if`( type(j, name), # fast but no fibre variable check
              UnitCount(),  op(2,j))
      end:
      
      
      # Jet order of a variable q
      
      varorder := proc(q)
        if type(q,'name') then 0
        else `count/length`(`jcount/inner`(q))
        fi
      end:
      
      jetorder := proc(f)
        min(op(map(varorder,vars(f))));
      end:
      
      jetorders := proc(f) # HB
        op(map(varorder,vars(f)))
      end:
      
      # Creating aliases for jet variables. Arguments are:
      # f1,...,fn,r, where r = jet order and 
      # f's are fibre variables (optional)
      
      `jet/aliases` := proc ()
        global `b/var/list`, `b/var/s`;
        local aux,flist,r;
        r := args[nargs];
        if nargs = 1 then flist := `f/var/list` 
        else flist := args[1..nargs-1] 
        fi;
        if not type (`b/var/list`,'list'(symbol)) then
          ERROR (`base variables must be symbols`) 
        fi;
        aux := expand((1 + convert(`b/var/s`,`+`))^r - 1);
        aux := map(proc(a) a/coeffs(a) end, [op(sort(aux, `b/var/list`))]);
        alias(op(map(proc(u,aux) if type(u,symbol) then
              op(map(proc(x,u) cat(u,'_',`bcount//str`(x)) = Jet(u,x) end,
                aux, u))
            else
              op(map(proc(x,u)
                  cat(op(0,u),'_',`bcount//str`(x))[op(u)] = Jet(u,x)
                end, aux, u))
            fi
          end, flist, aux)));
      end:
      
      `bcount//str` := proc (x)
        if type (x,'name') then x
        elif type (x,`^`) then 
          if op(2,x) > 3 then cat(op(2,x),op(1,x)) else op(1,x) $ op(2,x) fi
        elif type (x,`*`) then `bcount//str/_`(op(map(`bcount//str`, [op(x)])))
        else ERROR (`not a count`, x)
        fi 
      end:
      
      `bcount//str/_` := proc ()
        local i,a,b,ans;
        ans := args[1];
        for i from 2 to nargs do
          a := args[i-1]; b := args[i];
          if length(a) + length(b) > 2 then ans := ans,`_`,b else ans := ans,b fi
        od 
      end:
      
      `count//seq` := proc (x)
        if type (x,`^`) then `count//seq`(op(1,x)) $ op(2,x)
        elif type (x,`*`) then op(map(`count//seq`,[op(x)]))
      #  elif type (x,symbol) then x
      #  else cat(op(1,x),'_',`bcount//str`(op(2,x))) 
        else x
        fi
      end:
      
      
      
      
      
      #
      #   J e t s 
      #
      
      # creator
      jet := proc(u::`f/var`,x::`b/count1`) 
        `if`(type(x, unitcount), u, JET(u,`count/convert/inner`(x))) end;
      
      # creator of unevalued jets
      Jet := proc(u::`f/var`,x::`b/count1`) 
        `if`(type(x, unitcount), u, 'JET'(u,`count/convert/inner`(x))) end:
      
      # implementation
      JET := proc (u::`f/var`,x::`b/jcount`)
        option remember;
        local y0, y, ans, c;
        if remembertable(procname) = NULL then 'procname'(u,`count/normal`(x))
        else 
          for y0 in `b/var/s` do 
            y := `count/convert/inner`(y0);
            c := `count/`(x,y);
            if `test/count` (c) then
              if procname(u,c) <> evaln(procname(u,c)) then
                RETURN (`simpl/JET`(evalTD(TD(procname(u,c),y0))))
              fi
            fi 
          od;
          'procname'(u,`count/normal`(x))
        fi
      end:
      
      remembertable := proc (f) op(4,op(f)) end:

      
      `simpl/JET` := op(simpl):
      
      # ordering
      #`jet/<=` := proc(u,v)
      #  jfvar(u) = jfvar(v) and type(`count/`(jcount(v),jcount(u)), count)
      #end:
      
      #
      #   R e f r e s h i n g
      # 
      
      refresh := proc()
        map (`refresh/1`, `refresh/list`);
        op(map(proc(e) assign(Jet(lhs(e)) = simpl(eval(rhs(e)))) end, 
               `eqn/list`));
      end:
      
      `refresh/1` := proc(f) forget(f) end:
      
      `refresh/list` := [JET, Simpl, `pd//tab`,
        `vars/TD`,`vars/TD/1`,
        `pd/TD`,`pd/TD/1`,
        `pars/TD`,`pars/TD/1`,
        `unks/TD`,`unks/TD/1`,
        `Vars/TD`,`Vars/TD/1`]:
      
      
    end module  
  else
    error "Unknown jets implementation type name '%1'.", JetImplType
  fi:
  
  protect(jetsImplementationModule):
  with(jetsImplementationModule):
